namespace MouseGestures
{
    using System;
    using System.Windows.Forms;

    using WinAPI;

    ///<summary>
    ///	Captures mouse events necessary for mouse gesture recognition
    ///</summary>
    ///<remarks>
    ///	MouseMessageFilter implements <see cref="IMessageFilter">IMessageFilter</see> interface, it provides functionality
    ///	for the whole application.
    ///</remarks>
    internal class ManagedMouseFilter : IMessageFilter, IMouseMessageFilter
    {
        #region Fields

        private bool enabled;

        #endregion

        #region Constructors and Destructors

        public ManagedMouseFilter()
        {
            Application.AddMessageFilter(this);
        }

        ~ManagedMouseFilter()
        {
            Application.RemoveMessageFilter(this);
        }

        #endregion

        #region Public Events

        /// <summary>
        /// 	Occures when mouse is moved
        /// </summary>
        public event MouseFilterEventHandler MouseMove;

        /// <summary>
        /// 	Occures when right mouse button is pressed
        /// </summary>
        public event MouseFilterEventHandler RightButtonDown;

        /// <summary>
        /// 	Occures when right mouse button is relesed
        /// </summary>
        public event MouseFilterEventHandler RightButtonUp;

        #endregion

        #region Public Properties

        /// <summary>
        /// 	Gets or sets property indicating whether MouseMessageFilter is active and filtering messages
        /// </summary>
        public bool Enabled
        {
            get
            {
                return this.enabled;
            }
            set
            {
                this.enabled = value;
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// 	Implemets <see cref="IMessageFilter">IMessageFilter</see> interface
        /// </summary>
        /// <remarks>
        /// 	This function filters WM_RBUTTONDOWN and WM_RBUTTONUP messages
        /// 	before they are delivered to application. WM_MOUSEMOVE message is recorded
        /// 	only. When these messages appear the appropriate events of MouseMessageFilter are
        /// 	rised.
        /// </remarks>
        public bool PreFilterMessage(ref Message m)
        {
            if (this.enabled)
            {
                if (m.Msg == (int)MessageCodes.WM_MOUSEMOVE)
                {
                    this.RaiseRightButtonMoveEvent();

                    //pass WM_MOUSEMOVE message to the application
                    return false;
                }
                else if (m.Msg == (int)MessageCodes.WM_RBUTTONDOWN)
                {
                    this.RaiseRightButtonDownEvent();

                    return true;
                }
                else if (m.Msg == (int)MessageCodes.WM_RBUTTONUP)
                {
                    this.RaiseRightButtonUpEvent();

                    return true;
                }
            }
            return false;
        }

        #endregion

        #region Methods

        private void RaiseRightButtonDownEvent()
        {
            MouseFilterEventHandler temp = this.RightButtonDown;
            if (temp != null)
            {
                temp(this, EventArgs.Empty);
            }
        }

        private void RaiseRightButtonMoveEvent()
        {
            MouseFilterEventHandler temp = this.MouseMove;
            if (temp != null)
            {
                temp(this, EventArgs.Empty);
            }
        }

        private void RaiseRightButtonUpEvent()
        {
            MouseFilterEventHandler temp = this.RightButtonUp;
            if (temp != null)
            {
                temp(this, EventArgs.Empty);
            }
        }

        #endregion
    }
}